package component.fulltextsearch.index;

import java.io.IOException;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.TokenStream;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.document.Field.Index;
import org.apache.lucene.document.Field.Store;
import org.apache.lucene.queryParser.ParseException;
import org.apache.lucene.search.Filter;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.ScoreDoc;
import org.apache.lucene.search.Sort;
import org.apache.lucene.search.TopFieldDocs;
import org.apache.lucene.search.highlight.Highlighter;
import org.apache.lucene.search.highlight.QueryScorer;
import org.apache.lucene.search.highlight.SimpleFragmenter;
import org.apache.lucene.search.highlight.SimpleHTMLFormatter;

import component.fulltextsearch.constant.SearchConstant;
import component.fulltextsearch.util.AnalyzerUtil;
import component.fulltextsearch.util.Page;



/**
 * 简单搜索实现类
 *
 */
public class SimpleDocumentSearch implements IDocumentSearch{

	public Page queryPageData(String queryExpression, Date startDate,Date endDate, String field, String[] userArray, String[] roleArray, String[] sortFileds, int pageNo, int pageSize) throws IOException, ParseException {
		Filter filter = FilterBuilder.builderRightFilterIncludePub(userArray, roleArray);
		Query query = SearcherQueryBuilder.builderQuery(queryExpression, startDate, endDate, field);
		Sort sort = (sortFileds == null || sortFileds.length == 0) ? new Sort() : new Sort(sortFileds);
		return this.queryPageData(query, filter, sort, pageNo, pageSize);
	}
	
	public Page queryPageData(Query query, Filter filter, Sort sort, int pageNo, int pageSize) throws IOException {		
		int start = Page.getStartOfPage(pageNo, pageSize);
		int end = start + pageSize;
		IndexSearcher searcher = component.fulltextsearch.util.IndexFactoryUtil.getInstance().getIndexSearcher();
		TopFieldDocs topFieldDocs = searcher.search(query, filter, end, sort);
		List list = new ArrayList();
		Analyzer analyzer = AnalyzerUtil.getAnalyzer();
		for (int i = start ; i < topFieldDocs.scoreDocs.length; i ++) {
			ScoreDoc scoreDoc = topFieldDocs.scoreDocs[i];			
			Document document = searcher.doc(scoreDoc.doc);
			this.setHighLight(query, analyzer, document);
			list.add(document);
		}
		Page page = new Page(start, topFieldDocs.totalHits, pageSize, list);
		searcher.close();
		return page;
	}
	
	/**
	 * 让标题和显示内容中的关键字亮度显示
	 * 显示内容从摘要、正文内容或附件内容中关键字的地方开始抽取一段内容
	 * 默认显示摘要(没有亮度显示的内容)
	 * @param query
	 * @param analyzer
	 * @param document
	 * @throws IOException
	 */
	private void setHighLight(Query query,Analyzer analyzer,Document document) throws IOException{
		int len = 100;
		String name = document.get(SearchConstant.NAME_NAME);
		String summary = document.get(SearchConstant.NAME_SUMMARY);
		
		SimpleHTMLFormatter simpleHTMLFormatter = new SimpleHTMLFormatter("<font color='red'><em>", "</em></font>");
		Highlighter highlighter = new Highlighter(simpleHTMLFormatter,new QueryScorer(query));
		
		highlighter.setTextFragmenter(new SimpleFragmenter(name.length()));
		if (name != null && !"".equals(name.trim())) {
			TokenStream tokenStream = analyzer.tokenStream(SearchConstant.NAME_NAME,new StringReader(name));
			String highLightText = highlighter.getBestFragment(tokenStream,name);
			//System.out.println("标题 = " + highLightText);
			if(highLightText!=null){
				document.removeField(SearchConstant.NAME_NAME);
				document.add(new Field(SearchConstant.NAME_NAME, highLightText, Store.YES, Index.ANALYZED));
			}
		}
		
		String pageContent = null;
	
		if (summary != null && !"".equals(summary.trim())) {
			highlighter.setTextFragmenter(new SimpleFragmenter(summary.length()));
			
			TokenStream tokenStream = analyzer.tokenStream(SearchConstant.NAME_SUMMARY,new StringReader(summary));
			String highLightText = highlighter.getBestFragment(tokenStream,summary);
			//System.out.println("摘要" + highLightText);
			if(highLightText!=null){
				pageContent = highLightText;
			}
		}
		
		//如果摘要中没有搜索词的内容，就在正文内容中截取一段文字
		if(pageContent==null){
			String content = document.get(SearchConstant.NAME_CONTENT);
			if (content != null && !"".equals(content.trim())) {
				highlighter.setTextFragmenter(new SimpleFragmenter(len));
				
				TokenStream tokenStream = analyzer.tokenStream(SearchConstant.NAME_CONTENT,new StringReader(content));
				String highLightText = highlighter.getBestFragment(tokenStream,content);
				//System.out.println("摘要" + highLightText);
				if(highLightText!=null){
					pageContent = highLightText;
				}
			}
		}
		
		//如果正文内容中没有搜索词的内容，就在附件内容中截取一段文字
		if(pageContent==null){
			String attachmentContent = document.get(SearchConstant.NAME_ATTACHMENTCONTENT);
			if (attachmentContent != null && !"".equals(attachmentContent.trim())) {
				highlighter.setTextFragmenter(new SimpleFragmenter(len));
				
				TokenStream tokenStream = analyzer.tokenStream(SearchConstant.NAME_ATTACHMENTCONTENT,new StringReader(attachmentContent));
				String highLightText = highlighter.getBestFragment(tokenStream,attachmentContent);
				//System.out.println("摘要" + highLightText);
				if(highLightText!=null){
					pageContent = highLightText;
				}
			}
		}
		
		//如果都没有包含搜索词的内容就显示摘要
		if(pageContent==null){
			pageContent = summary;
		}
		
		if(pageContent!=null && !"".equals(pageContent)){
			String filterStr = "[.,;:!?)、。，；：！？）]";
			Pattern p = Pattern.compile(filterStr);
			Matcher fMatcher = p.matcher(String.valueOf(pageContent.charAt(0)));
			if(fMatcher.matches()){
				pageContent = pageContent.substring(1);
			}
		}
		
		document.add(new Field(SearchConstant.PAGE_CONTENT, pageContent, Store.YES, Index.ANALYZED));
		
	}
	
	public static void main(String[] args) {
		String filterStr = "[.,;:!、。，；：！]";
		Pattern p = Pattern.compile(filterStr);
		
		Matcher fMatcher = p.matcher(".");
		System.out.println(fMatcher.matches());
		
		fMatcher = p.matcher(",");
		System.out.println(fMatcher.matches());
		
		fMatcher = p.matcher(";");
		System.out.println(fMatcher.matches());
		
		fMatcher = p.matcher(":");
		System.out.println(fMatcher.matches());
		
		fMatcher = p.matcher("!");
		System.out.println(fMatcher.matches());
		
		
		
		fMatcher = p.matcher("。");
		System.out.println(fMatcher.matches());
		
		fMatcher = p.matcher("，");
		System.out.println(fMatcher.matches());
		
		fMatcher = p.matcher("；");
		System.out.println(fMatcher.matches());
		
		fMatcher = p.matcher("：");
		System.out.println(fMatcher.matches());
		
		fMatcher = p.matcher("！");
		System.out.println(fMatcher.matches());
		
		fMatcher = p.matcher("、");
		System.out.println(fMatcher.matches());
		
	}

}
